package com.doliere.android.app.p2p.threads;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;

import com.doliere.android.app.p2p.services.P2pService;

import android.annotation.SuppressLint;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.os.AsyncTask;

/**
 * 
 * @author doliere
 * This thread handle a connection request to a peer.
 * Once the connection is established, the connection informations are returned to the
 * user so that a socket communication can be setted up.
 */
public class P2pConnectToAPeer extends AsyncTask<WifiP2pDevice, Hashtable<String, Boolean>, Hashtable<String, Socket>>{
	
	private WifiP2pManager mManager;
	private Channel mChannel;
	private P2pService mService;
	private String mDeviceAddress;
	private Hashtable<String, WifiP2pInfo> mDeviceConnectionInfos;
	private Hashtable<String, Boolean> mDeviceConnected;
	private Socket mClient;
	private ServerSocket mServerSocket;
	private boolean isOk = false;
	
	public P2pConnectToAPeer(WifiP2pManager manager, Channel channel, P2pService service, ServerSocket ss){
		mManager = manager;
		mChannel = channel;
		mService = service;
		mDeviceConnectionInfos = new Hashtable<String, WifiP2pInfo>();
		mDeviceConnected = new Hashtable<String, Boolean>();
		mServerSocket = ss;
		mClient = new Socket();
	}
	
	//In this method, we try to establish a connection to a particular peer

	@SuppressLint("NewApi")
	@Override
	protected Hashtable<String, Socket> doInBackground(WifiP2pDevice... params) {
		WifiP2pConfig config = new WifiP2pConfig();
		config.groupOwnerIntent = 15; // 
		config.deviceAddress = params[0].deviceAddress;
		mDeviceAddress = params[0].deviceAddress;
		
		mManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
			
			@SuppressWarnings("unchecked")
			@Override
			public void onSuccess() {
				mDeviceConnected.put(mDeviceAddress, true);
				publishProgress(mDeviceConnected);
				mManager.requestConnectionInfo(mChannel, new WifiP2pManager.ConnectionInfoListener() {
					
					@Override
					public void onConnectionInfoAvailable(WifiP2pInfo info) {
						if(mDeviceConnectionInfos.contains(mDeviceAddress))
							mDeviceConnectionInfos.remove(mDeviceAddress);
						mDeviceConnectionInfos.put(mDeviceAddress, info);
						
						//onPostExecute(mDeviceConnectionInfos); // Force the connection to render
						
						/*
						 * If the device is the groupe owner, wait for an incoming connection.
						 * else try to connect to the group owner informations.
						 */
						if(info.groupFormed && info.isGroupOwner){
							try {
								mClient = mServerSocket.accept();
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}else if(info.groupFormed && !info.isGroupOwner){
							try {
								mClient.bind(null);
								mClient.connect(new InetSocketAddress(info.groupOwnerAddress, mServerSocket.getLocalPort()));
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}
				});
			}
			
			@SuppressWarnings("unchecked")
			@Override
			public void onFailure(int reason) {
				mDeviceConnected.put(mDeviceAddress, false);
				publishProgress(mDeviceConnected);
			}
		});
		return null;
	}
	
	@Override
	public void onProgressUpdate(Hashtable<String, Boolean>...hashtables){
		mService.setConnectedDevices(hashtables[0]);
	}
	
	@Override
	public void onPostExecute(Hashtable<String, Socket> result){
	}
}
